package com.mangix.http;

import com.mangix.core.MangixMonitor;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Ahan on 2014/5/28.
 */
public class MangixMonitorServlet extends HttpServlet {
    private MangixMonitor monitor;

    public MangixMonitorServlet(MangixMonitor monitor) {
        this.monitor = monitor;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String pathInfo = req.getRequestURI();
        if (pathInfo == null) {
            resp.sendError(404);
            return;
        }
        String path = pathInfo.substring(1);
        if (path.equals("")) {
            resp.sendError(404);
            return;
        }
        switch (path) {
            case "nodes":


                System.out.println("Get information of the nodes.");
                List<Map<String, Object>> nodesInfo = monitor.getNodes();
                String state = monitor.getState();
                long object_num = 0;
                long usedSpace = 0;
                Map<String, Object> availableSpaces = new HashMap<>();
                for (Map<String, Object> nodeInfo : nodesInfo) {
                    object_num += ((Number)nodeInfo.get("object_num")).longValue();
                    usedSpace += ((Number)nodeInfo.get("used_space")).longValue();
                    availableSpaces.put((String)nodeInfo.get("hostname"), nodeInfo.get("available_space"));
                }
                long availableSpace = 0;
                for (Object o : availableSpaces.values()) {
                    availableSpace += ((Number)o).longValue();
                }

                PrintWriter out = resp.getWriter();
                out.println("<html>");
                out.println("<head><meta http-equiv=Content-Type content=\"text/html;charset=utf-8\">");
                out.println("\t<title>Mangix Monitor Platform</title>");
                out.println("</head>");
                out.println("<body>");
                out.println("\t<center><h2>Mangix Monitor Platform</h2></center>");
                out.println("\t<center><table border=\"1\">");
                out.println("\t\t<tr><th>Number of nodes</th><td>" + nodesInfo.size() + "</td></tr>");
                out.println("\t\t<tr><th>State</th><td>" + state + "</td></tr>");
                out.println("\t\t<tr><th>Number of keys</th><td>" + object_num + "</td></tr>");
                out.println("\t\t<tr><th>Occupied space</th><td>" + humanReadableByteCount(usedSpace, false) + "/" + humanReadableByteCount(availableSpace, false) + "(" + usedSpace * 100 / availableSpace + "%)</td></tr>");
                out.println("\t</table></center>");
                out.println("<br/>");
                out.println("\t<center><table border=\"1\">");
                out.println("\t\t<tr><th>Node</th><th>State</th><th>Number of keys</th><th>Used Space</th><th>Available Space</th></tr>");
                for (Map<String, Object> nodeInfo : nodesInfo) {
                    out.printf("\t\t<tr><th>%s</th><th>%s</th><th>%s</th><th>%d</th><th>%d</th></tr>", nodeInfo.get("hostname").toString() + ":" + nodeInfo.get("port"), "Normal", nodeInfo.get("object_num"),  nodeInfo.get("used_space"), nodeInfo.get("available_space"));
                }
                out.println("\t</table></center>");
                out.println("</body>");
                out.println("</html>");
                out.flush();
                out.close();
                break;
            default:
                break;
        }


    }

    public String humanReadableByteCount(long bytes, boolean si) {
        int unit = si ? 1000 : 1024;
        if (bytes < unit) return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "");
        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        if (requestURI == null) {
            resp.sendError(404);
            return;
        }
        String path = requestURI.substring(1);
        if (path.equals("")) {
            resp.sendError(404);
            return;
        }
        switch (path) {
            case "report":
                InputStream in = null;
                try {
                    in = req.getInputStream();
                    byte[] buffer = new byte[1024 * 512];
                    int startPosition = 0, readLength;
                    while ((readLength = in.read(buffer, startPosition, buffer.length)) != -1) {
                        startPosition += readLength;
                    }
                    String reportContent = new String(buffer, 0, startPosition);
                    monitor.update(reportContent);
                } catch(Exception e) {
                    e.printStackTrace();
                } finally {
                    if (in != null) in.close();
                }
                break;
            default:
                break;
        }
    }
}
